package com.dreamcar.auction.ejb;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.xml.ws.WebServiceRef;

import com.dreamcar.auction.entity.Bid;
import com.dreamcar.auction.entity.CarModel;
import com.dreamcar.auction.entity.Component;
import com.dreamcar.auction.entity.DestinationMarket;
import com.dreamcar.auction.entity.PurchaseOrder;
import com.dreamcar.auction.entity.Request;
import com.dreamcar.auction.entity.Supplier;
import com.dreamcar.auction.entity.eao.ReverseAuctionEAOLocal;
import com.dreamcar.auction.enums.RequestStatusEnum;
import com.dreamcar.auction.exception.InvalidBidRequestException;
import com.dreamcar.auction.helper.InventoryWSClientHelper;
import com.dreamcar.inventory.util.MailSenderUtil;
import com.dreamcar.inventory.ws.Inventory;
import com.dreamcar.inventory.ws.InventoryService;
import com.dreamcar.inventory.ws.RequestDTO;

@Stateless
public class ReverseAuctionFacade implements ReverseAuctionFacadeLocal {

	@EJB
	private ReverseAuctionEAOLocal reverseAuctionEAO;
	
	@WebServiceRef
	private InventoryService inventoryService;
	private Inventory inventory;
	
	public ReverseAuctionFacade() {
		inventory = inventoryService.getInventoryPort();
	}
	
	public List<DestinationMarket> findAllDestinationMarket() {
		return reverseAuctionEAO.findAllDestinationMarket();
	}
	
	public List<CarModel> findCarModelByDestinationMarket(
			Integer idDestinationMarket) {
		return reverseAuctionEAO.findCarModelByDestinationMarket(idDestinationMarket);
	}
	
	public List<Component> findCarComponentByCarModel(Integer idCarModel, String discriminator) {
		return reverseAuctionEAO.findCarComponentByCarModel(idCarModel, discriminator);
	}
	
	
	//*** Solo operaciones a BD ***//
	
	public Request updateRequest(Request entity) {
		return reverseAuctionEAO.updateRequest(entity);
	}
	
	public Set<Bid> findBidsRequest(Integer requestId){
		return reverseAuctionEAO.findBidsByRequest(requestId);
	}
	
	public List<Request> findRequestByExampleAndComponent(Request example, Integer idComponent){
		example.setComponent(reverseAuctionEAO.getComponentReferenceById(idComponent));
		return findRequestByExample(example);
	}
	
	private List<Request> findRequestByExample(Request example){
		return reverseAuctionEAO.findRequestByExample(example);
	}
	
	//*** Contienen Logica de Negocio ***//
	@Override
	public void validateAndSaveRequest(RequestDTO requestDTO, Request request,
			Integer componentId, String username)
		throws InvalidBidRequestException{
		if(!InventoryWSClientHelper.validateRequest(requestDTO)){
			throw new InvalidBidRequestException("The Request received is not valid");
		}
		reverseAuctionEAO.saveRequest(request, componentId, username);
	}
	
	public void issuePO(Integer requestId, Integer bidId, String username){
		PurchaseOrder purchaseOrder = reverseAuctionEAO.savePO(requestId, bidId);
		//Enviar correo
		Supplier supplier = reverseAuctionEAO.findSupplierByUsername(username);
		MailSenderUtil.sendIssuePOMail(purchaseOrder, supplier.getName(), supplier.getEmail());
	}
	
	@Override
	public void scheduleWork(RequestDTO requestDTO, Integer requestId, RequestStatusEnum status) {
		Request request = reverseAuctionEAO.getRequestReferenceById(requestId);
		request.setStatus(status.toValue());
		reverseAuctionEAO.updateRequest(request);
		InventoryWSClientHelper.scheduleWorkInFactory(requestDTO);
	}
	
	public void submitBid(Bid bid, Integer requestId, String username) throws InvalidBidRequestException{
		Request request = reverseAuctionEAO.getRequestReferenceById(requestId);
		validatePriceThreshold(new BigDecimal(bid.getAmount()), request.getPriceThreshold());
		bid.setRequest(request);
		reverseAuctionEAO.saveBid(bid, username);
	}
	
	private void validatePriceThreshold(BigDecimal amount, BigDecimal priceThresold)
			throws InvalidBidRequestException{
		if(priceThresold.compareTo(amount)==-1){
			throw new InvalidBidRequestException("The bid amount must be equal or greater than price request");
		}
	}
	
	public void chooseWinnerBid(){
		List<Request> lstRequest = 
			findRequestByExample(new Request(null, null, null, null, null, RequestStatusEnum.OPEN.toValue(), null, null));
		for (Request request : lstRequest) {
			if(request.getBids().isEmpty()){
				continue;
			}else if(new Date().after(new Date(request.getFinishDate().getTime()))){
				Set<Bid> bids = request.getBids();
				Bid winner = getMinAmountBid(bids);
				winner.setWinner(true);
				reverseAuctionEAO.updateBid(winner);
				request.setStatus(RequestStatusEnum.CLOSED.toValue());
				reverseAuctionEAO.updateRequest(request);
			}
		}
	}
	
	private Bid getMinAmountBid(Set<Bid> bids){
		if(bids.isEmpty()){
			return null;
		}
		List<Bid> lstBids = new ArrayList<Bid>(bids);
		Bid winner = lstBids.get(0);
		for (Bid bid : bids) {
			if(new Integer(winner.getAmount())>new Integer(bid.getAmount())){
				winner = bid;
			}
		}
		System.out.println("Winner Bid Ganador ID: "+winner.getIdBid());
		return winner;
	}
	
}